/*********************************************************************
 * Filename:      list.h
 *                
 * It belongs to goblin-os.
 *                
 * Version:       
 * Author:        Ins <InsFous@gmail.com>
 * Created at:    Fri Dec 10 17:49:27 2010
 * Description:   
 *                
 ********************************************************************/
#ifndef _GOBLIN_LIBRARY_LIST_H_
#define _GOBLIN_LIBRARY_LIST_H_

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

struct list_head {
  struct list_head *prev, *next;
};

#define LIST_HEAD_INIT(name) {&(name), &(name)};

#define LIST_HEAD(name)				\
  struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list) {
  list->prev = list;
  list->next = list;
  }

static inline void __list_add(struct list_head *new_node, struct list_head *prev, struct list_head *next) {
  new_node->prev = prev;
  new_node->next = next;
  prev->next = new_node;
  next->prev = new_node;
}

static inline void list_add(struct list_head *new_node, struct list_head *head) {
  __list_add(new_node, head, head->next);
}

static inline void list_add_tail(struct list_head *new_node, struct list_head *head) {
  __list_add(new_node, head->prev, head);
  }

static inline void __list_del(struct list_head *prev, struct list_head *next) {
  next->prev = prev;
  prev->next = next;
}

static inline void list_del(struct list_head *entry) {
  __list_del(entry->prev, entry->next);
  entry->prev = NULL;
  entry->next = NULL;
}

static inline void list_replace(struct list_head *old, struct list_head *new_node) {
  new_node->prev = old->prev;
  new_node->next = old->next;
  old->prev->next = new_node;
  old->next->prev = new_node;
}

static inline int list_empty(struct list_head *head) {
    return head->next == head;
}

#define list_entry(ptr, type, member)				\
  ((type *)((char *)ptr - (unsigned long)&((type *)0)->member))


#define list_for_each(pos, head)				\
  for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_forward(pos, head)			\
  for (pos = (head)->prev; pos != (head); pos = pos->prev)


#endif  // _GOBLIN_LIBRARY_LIST_H_
